package com.example.project3.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.project3.entity.User;
import com.example.project3.exception.ServiceException;
import com.example.project3.mapper.UserMapper;
import com.example.project3.service.UserService;
import com.example.project3.service.email.MyEmail;
import com.example.project3.util.Encryption;
import com.example.project3.util.MyJWT;
import com.example.project3.util.VerificationCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author 23931
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2023-05-29 19:20:56
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    private final static String KEY_EMAIL_CODE = "emailCode:";
    private VerificationCode verificationCode;
    private MyEmail myEmail;
    @Value("${email.expiration}")
    private Integer emailExpiration;
    private StringRedisTemplate stringRedisTemplate;
    private UserMapper userMapper;
    private Encryption encryption;
    private com.example.project3.service.ICS.ICSServiceImpl ICSServiceImpl;
    private MyJWT myJWT;
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public void sendCode(String email) {
        //查找次邮箱是否已被注册
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("email", email);
        List<User> users = userMapper.selectByMap(map);
        if (users.size() != 0) {
            throw new ServiceException("此邮箱已被注册");
        }
        String code;
        //检查是否有缓存
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(KEY_EMAIL_CODE + email))) {
            code = stringRedisTemplate.opsForValue().get(KEY_EMAIL_CODE + email);
        } else {
            //生成验证码
            code = verificationCode.getVerificationCodeString();
        }
        //发送验证码
        myEmail.sendEmail(email, code);
        //信息放redis
        stringRedisTemplate.opsForValue().set(KEY_EMAIL_CODE + email, code, emailExpiration, TimeUnit.MINUTES);
    }

    @Override
    public boolean verifyCode(String email, String code) {
        String code_ = stringRedisTemplate.opsForValue().get(KEY_EMAIL_CODE + email);
        if (code_ == null) {
            return false;
        } else if (code_.equals(code)) {
            stringRedisTemplate.delete(KEY_EMAIL_CODE + email);
            return true;
        } else {
            return false;
        }
    }

    //登录方法
    @Override
    public String login(User user) {
        //获取数据库里存放的用户名
        String email = user.getEmail();
        //获取密码
        String password = user.getPassword();
        if (email == null || password == null) {
            throw new ServiceException("邮箱密码为空");
        }
        LambdaQueryWrapper<User> userLambdaQueryWrapper = Wrappers.lambdaQuery(User.class);
        userLambdaQueryWrapper.eq(User::getEmail, email);
        userLambdaQueryWrapper.eq(User::getPassword, encryption.str(encryption.MD5(password), 32));
        User userOne = userMapper.selectOne(userLambdaQueryWrapper);
        if (Objects.isNull(userOne)) {
            throw new ServiceException("邮箱密码错误或不存在");
        }
        String token = myJWT.create(userOne);
        //保存到redis中
        redisTemplate.opsForValue().set(token, "", 4L, TimeUnit.DAYS);
        return token;
    }


    @Override
    public boolean register(User user) {
        user.setPassword(encryption.str(encryption.MD5(user.getPassword()), 32));
        return userMapper.insert(user) == 1;
    }

    @Autowired
    public void setVerificationCode(VerificationCode verificationCode) {
        this.verificationCode = verificationCode;
    }

    @Autowired
    public void setMyEmail(MyEmail myEmail) {
        this.myEmail = myEmail;
    }

    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Autowired
    public void setEncryption(Encryption encryption) {
        this.encryption = encryption;
    }

    @Autowired
    public void setICSServiceImpl(com.example.project3.service.ICS.ICSServiceImpl icsServiceImpl) {
        this.ICSServiceImpl = icsServiceImpl;
    }

    @Autowired
    public void setMyJWT(MyJWT myJWT) {
        this.myJWT = myJWT;
    }


    public void updateUsername(User user) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        Integer uid = myJWT.getUid(request);
        user.setUid(uid);
        userMapper.updateById(user);

    }

    @Qualifier("redisTemplate")
    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}




